﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using KingOfCSharp.iHunter;

namespace KingOfCSharp.iHunter.UI
{
    public partial class MessageContainer : UserControl
    {
        private Dictionary<Guid, IMessageEditor> editors;
        private Dictionary<Guid, IMessageViewer> viewers;
        private IMessageEditor defaultEditor;
        private IMessageViewer defaultViewer;
        private LocalClient client;
        private List<IAttachment> editorAttachments;
        public LocalClient Client
        {
            get { return client; }
            set { client = value; }
        }
        private bool editingMode;
        private Message message;
        private Control currentControl;
        private IAttachment lastClickedAttachment;
        private LinkLabel lastClickedLink;
        private Guid channelGuid;
        private Guid providerGuid;

        public Guid ChannelGuid
        {
            get { return channelGuid; }
        }
        private Guid replyGuid;

        private IMessageEditor GetEditor(Message message)
        {
            if (message.EditorGuid != Guid.Empty)
            {
                IMessageEditor editor;
                if (editors.TryGetValue(message.EditorGuid, out editor))
                {
                    return editor;
                }
                else
                {
                    IEditorProvider provider;
                    if (client.EditorProvidersDictionary.TryGetValue(message.EditorGuid, out provider))
                    {
                        IMessageEditor newEditor = provider.CreateEditorInstance();
                        if (newEditor != null && newEditor is Control)
                        {
                            if (this.ControlCreated != null)
                                ControlCreated(this, new MessageControlEventArgs(provider.Guid, newEditor as Control));
                            editor = newEditor;
                            providerGuid = provider.Guid;
                            this.components.Add(newEditor as Control);
                        }
                        else
                        {
                            providerGuid = KingOfCSharp.iHunter.UI.HtmlEditorProvider.Guid;
                            editor = defaultEditor;
                        }
                        editors[message.EditorGuid] = (editor);

                        if (this.ControlActived != null)
                            ControlActived(this, new MessageControlEventArgs(provider.Guid, editor as Control));

                        editor.UpdateCommandUI += new CommandUIEventHandler(editor_UpdateCommandUI);
                        return editor;
                    }
                    else
                    {
                        if (this.ControlActived != null)
                            ControlActived(this, new MessageControlEventArgs(HtmlEditorProvider.Guid, defaultEditor as Control));
                        defaultEditor.UpdateCommandUI += new CommandUIEventHandler(editor_UpdateCommandUI);
                        providerGuid = KingOfCSharp.iHunter.UI.HtmlEditorProvider.Guid;
                        return defaultEditor;
                    }
                }

            }
            if (this.ControlActived != null)
                ControlActived(this, new MessageControlEventArgs(HtmlEditorProvider.Guid, defaultEditor as Control));
            defaultEditor.UpdateCommandUI += new CommandUIEventHandler(editor_UpdateCommandUI);
            providerGuid = KingOfCSharp.iHunter.UI.HtmlEditorProvider.Guid;
            return defaultEditor;
        }

        void editor_UpdateCommandUI(object sender, CommandUIEventArgs e)
        {
            if (this.UpdateCommandUI != null)
                UpdateCommandUI(this, e);
        }
        private IMessageViewer GetViewer(Message message)
        {
            if (message.ViewerGuid != Guid.Empty)
            {
                IMessageViewer viewer;
                if (viewers.TryGetValue(message.ViewerGuid, out viewer))
                {
                    return viewer;
                }
                else
                {
                    IViewerProvider provider;
                    if (client.ViewerProvidersDictionary.TryGetValue(message.ViewerGuid, out provider))
                    {
                        IMessageViewer newViewer = provider.CreateViewerInstance();

                        if (newViewer != null && newViewer is Control)
                        {
                            if (this.ControlCreated != null)
                                ControlCreated(this, new MessageControlEventArgs(provider.Guid, newViewer as Control));

                            viewer = newViewer;
                            this.components.Add(newViewer as Control);
                        }
                        else
                        {
                            viewer = defaultViewer;
                        }
                        viewers[message.ViewerGuid] = (viewer);

                        if (this.ControlActived != null)
                            ControlActived(this, new MessageControlEventArgs(provider.Guid, viewer as Control));
                        viewer.UpdateCommandUI += new CommandUIEventHandler(viewer_UpdateCommandUI);
                        return viewer;
                    }
                    else
                    {
                        if (this.ControlActived != null)
                            ControlActived(this, new MessageControlEventArgs(HtmlViewerProvider.Guid, defaultViewer as Control));
                        defaultViewer.UpdateCommandUI += new CommandUIEventHandler(viewer_UpdateCommandUI);
                        return defaultViewer;
                    }
                }

            }
            if (this.ControlActived != null)
                ControlActived(this, new MessageControlEventArgs(HtmlViewerProvider.Guid, defaultViewer as Control));
            defaultViewer.UpdateCommandUI += new CommandUIEventHandler(viewer_UpdateCommandUI);
            return defaultViewer;
        }

        void viewer_UpdateCommandUI(object sender, CommandUIEventArgs e)
        {
            if (this.UpdateCommandUI != null)
                UpdateCommandUI(this, e);
        }
        public MessageContainer()
        {
            InitializeComponent();
            client = null;
            channelGuid = Guid.Empty;
            currentControl = null;
            editors = new Dictionary<Guid, IMessageEditor>();
            viewers = new Dictionary<Guid, IMessageViewer>();
            defaultEditor = new HtmlMessageEditor();
            defaultViewer = new HtmlMessageViewer();

            editorAttachments = new List<IAttachment>();
        }

        protected FlowLayoutPanel AttachmentListPanel
        {
            get
            {
                return attachmentListPanel;
            }
        }

        protected Panel ChannelSelectingPanel
        {
            get
            {
                return channelSelectingPanel;
            }
        }

        protected Panel ViewerPanel
        {
            get
            {
                return viewerPanel;
            }
        }
        private bool isModified;
        public bool IsModified
        {
            get
            {
                if (editingMode)
                {
                    IMessageEditor editor = currentControl as IMessageEditor;
                    if (isModified)
                        return true;
                    return editor.MessageModified;
                }
                else
                {
                    return false;
                }
            }
            set
            {
                isModified = value;
                if (editingMode)
                {
                    IMessageEditor editor = currentControl as IMessageEditor;
                    editor.MessageModified = value;
                }
            }
        }
        public bool EditingMode
        {
            get
            {
                return editingMode;
            }
        }

        public void LoadMessage(Message message)
        {
            editorAttachments.Clear();
            this.message = new Message(message.Guid, message);

            
            if (client.Drafts.IsAncestorOf(message.Folder))
            {
                editingMode = true;
            }
            else
            {
                editingMode = false;
            }

            this.SuspendLayout();

            Control control = null;
            if (editingMode)
            {
                IMessageEditor editor = GetEditor(message);
                control = editor as Control;
                editor.ImportMessage(message);
                channelSelectingPanel.Visible = true;
                
                comboBox1.Items.Clear();

                ComboBoxItem item = new ComboBoxItem();
                ChannelInfo info = client.GetChannelInfo(this.message.ChannelGuid);
                item.Text = "Current - " + ((info.Guid != Guid.Empty)?(info.Name):("(Unknown)"));
                item.Guid = message.ChannelGuid;
                if (message.ChannelGuid != Guid.Empty)
                {
                    this.comboBox1.Items.Add(item);
                    this.comboBox1.SelectedIndex = 0;
                }
                foreach (ChannelInfo channelInfo in client.GetChannelInfos())
                {
                    IChannelProvider chProvider;
                    if (client.ChannelProvidersDictionary.TryGetValue(channelInfo.ProviderGuid, out chProvider))
                    {
                        IEditorProvider provider;
                        if (client.EditorProvidersDictionary.TryGetValue(chProvider.NewMesssageEditorGuid, out provider))
                        {
                            Guid currentGuid = new Guid();
                            if (editor is HtmlMessageEditor)
                                currentGuid = HtmlEditorProvider.Guid;
                            else
                                currentGuid = message.EditorGuid;


                            if (provider.Guid == currentGuid)
                            {
                                ComboBoxItem chItem = new ComboBoxItem();
                                chItem.Text = channelInfo.Name;
                                chItem.Guid = channelInfo.Guid;
                                this.comboBox1.Items.Add(chItem);
                            }
                        }
                        else if (editor is HtmlMessageEditor)
                        {
                            ComboBoxItem chItem = new ComboBoxItem();
                            chItem.Text = channelInfo.Name;
                            chItem.Guid = channelInfo.Guid;
                            this.comboBox1.Items.Add(chItem);
                        }

                    }
                }

                foreach (IAttachment attachment in message.Attachments)
                {
                    editorAttachments.Add(new Attachment(attachment.Guid, attachment));
                }
            }
            else
            {
                channelSelectingPanel.Visible = false;
                IMessageViewer viewer = GetViewer(message);
                control = viewer as Control;
                viewer.DisplayMessage(message);
            }

            replyGuid = message.ReplyGuid;
            if (control != currentControl)
            {
                if (currentControl != null)
                {
                    viewerPanel.Controls.Remove(currentControl);
                }
                viewerPanel.Controls.Add(control);
                control.Dock = DockStyle.Fill;
                currentControl = control;
            }

            LoadAttachments(message);

            this.ResumeLayout();

        }

        public void LoadAttachments(Message message)
        {
            editorAttachments.Clear();
            foreach (IAttachment attachment in message.Attachments)
            {
                editorAttachments.Add(new Attachment(attachment.Guid, attachment));
            }

            this.attachmentListPanel.Controls.Clear();

            if (message.Attachments.Count > 0)
            {
                this.attachmentListPanel.Visible = true;
                foreach (IAttachment attachment in message.Attachments)
                {
                    IAttachment temp = attachment;
                    Guid attachmentGuid = attachment.Guid;
                    LinkLabel link = new LinkLabel();
                    link.Text = attachment.FileName;
                    link.AutoSize = true;
                    link.BackColor = Color.Transparent;
                    link.Margin = new Padding(5);
                    link.LinkClicked += delegate(object sender, LinkLabelLinkClickedEventArgs e)
                    {
                        IAttachment a = Client.FindAttachmentByGuid(attachmentGuid);
                        if (a == null)
                            a = temp;
                        lastClickedAttachment = a;
                        lastClickedLink = link;
                        string ext = System.IO.Path.GetExtension(a.LocalPath);
                        if (ImagePreviewWindow.IsFileExtensionSupported(ext))
                        {
                            previewToolStripMenuItem.Enabled = true;
                        }
                        else
                        {
                            previewToolStripMenuItem.Enabled = false;
                        }
                        if (editingMode)
                        {
                            editingAttachmentContextMenu.Show(link, link.Width / 2, 0);
                        }
                        else
                        {
                            if (System.IO.File.Exists(a.LocalPath) && e.Button == MouseButtons.Left)
                            {
                                if (ImagePreviewWindow.IsFileExtensionSupported(ext))
                                    OnAttachmentLinkClick(a, AttachmentAction.Preview);
                                else
                                    OnAttachmentLinkClick(a, AttachmentAction.Save);
                            }
                            else
                            {
                                viewAttachentContextMenu.Show(link, link.Width / 2, 0);
                            }
                        }
                    };

                    if (attachment.Description.Length > 0)
                    {
                        link.Text += "(" + attachment.Description + ")";
                    }
                    attachmentListPanel.Controls.Add(link);
                }
                //this.ResumeLayout(false);
                //this.PerformLayout();
            }
            else
            {
                attachmentListPanel.Visible = false;
            }
        }

        public Message GetMessage()
        {
            if (editingMode)
            {
                IMessageEditor editor = currentControl as IMessageEditor;
                IMessage message = null;
                try
                {
                    message = editor.GetMessage();
                }
                catch
                {
                }

                if (message == null)
                    return null;
                this.message = new Message(message.Guid, message);
                this.message.ChannelGuid = channelGuid;
                this.message.ReplyGuid = replyGuid;
                this.message.EditorGuid = providerGuid;
                foreach (IAttachment attachment in editorAttachments)
                {
                    this.message.Attachments.Add(attachment);
                }
                return this.message;
            }
            else
            {
                return null;
            }
        }

        public Message GetDraft()
        {
            if (editingMode)
            {
                IMessageEditor editor = currentControl as IMessageEditor;
                IMessage message = null;
                try
                {
                    message = editor.GetDraft();
                }
                catch
                {
                }
                this.message = new Message(message.Guid, message);
                this.message.ChannelGuid = channelGuid;
                this.message.ReplyGuid = replyGuid;
                this.message.Attachments.Clear();
                this.message.EditorGuid = providerGuid;
                foreach (IAttachment attachment in editorAttachments)
                {
                    this.message.Attachments.Add(attachment);
                }
                return this.message;
            }
            else
            {
                return message;
            }
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            message.Attachments.Remove(lastClickedAttachment);
            attachmentListPanel.Controls.Remove(lastClickedLink);
            this.PerformLayout();
            this.isModified = true;
            foreach (IAttachment attachment in editorAttachments)
            {
                if (lastClickedAttachment.Guid == attachment.Guid)
                {
                    editorAttachments.Remove(attachment);
                    break;
                }
            }
        }

        public event AttachmentClickEventHandler AttachmentLinkClick;
        public event MessageControlEventHandler ControlCreated;
        public event MessageControlEventHandler ControlActived;
        public event CommandUIEventHandler UpdateCommandUI;
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBoxItem item = (ComboBoxItem)comboBox1.SelectedItem;

            this.channelGuid = (Guid)item.Guid;
        }

        private void MessageContainer_Load(object sender, EventArgs e)
        {
        }

        public void ExecuteCommand(CommandUIEventArgs e)
        {
            if (editingMode)
            {
                IMessageEditor editor = currentControl as IMessageEditor;

                editor.ExcuteCommand(e);

            }
            else
            {
                IMessageViewer viewer = currentControl as IMessageViewer;
                viewer.ExcuteCommand(e);
            }
        }

        protected virtual void downloadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnAttachmentLinkClick(lastClickedAttachment, AttachmentAction.Download);
        }

        private void OnAttachmentLinkClick(IAttachment attachment, AttachmentAction action)
        {
            if (AttachmentLinkClick != null)
                AttachmentLinkClick(this, new AttachmentClickEventArgs(attachment.Guid, action));
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnAttachmentLinkClick(lastClickedAttachment, AttachmentAction.Save);
        }

        private void previewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnAttachmentLinkClick(lastClickedAttachment, AttachmentAction.Preview);
        }

    }

    public enum AttachmentAction
    {
        None = 0,
        Download,
        Save,
        Delete,
        Preview
    }
    public class AttachmentClickEventArgs : EventArgs
    {
        private Guid attachmentGuid;
        private AttachmentAction action;

        public Guid AttachmentGuid
        {
            get { return attachmentGuid; }
        }

        public AttachmentAction Action
        {
            get
            {
                return action;
            }
        }

        public AttachmentClickEventArgs(Guid attachmentGuid, AttachmentAction action)
        {
            this.attachmentGuid = attachmentGuid;
            this.action = action;
        }
    }

   
    public delegate void AttachmentClickEventHandler(object sender, AttachmentClickEventArgs e);

    internal struct ComboBoxItem
    {
        public string Text { get; set; }
        public Guid Guid { get; set; }
    }

    public class MessageControlEventArgs : EventArgs
    {
        private Control control;

        public Control Control
        {
            get { return control; }
        }
        private Guid providerGuid;

        public Guid ProviderGuid
        {
            get { return providerGuid; }
        }

        public MessageControlEventArgs(Guid ProviderGuid, Control control)
        {
            this.control = control;
            this.providerGuid = ProviderGuid;
        }

    }



    public delegate void MessageControlEventHandler(object sender, MessageControlEventArgs e);
}
